#include <func.h>

int sendFd(int sfd,int fd)
{
    struct msghdr msg;
    bzero(&msg,sizeof(msg));    //切记先清空！！！！！掌控所有的值

    //从用户态给对方的信息
    struct iovec iov[1];        //这里写成 iov[1] 是为了传递iov的时候直接就是指针
    char iov_buf[29] = "iov_buf from sendFd";
    iov[0].iov_base = iov_buf;
    iov[0].iov_len = strlen(iov_buf);
    msg.msg_iov = iov;
    msg.msg_iovlen = 1;

    //内核给的信息 （就是给对方描述符fd）
    struct cmsghdr * cmsg;
    int len = CMSG_LEN(sizeof(int));
    cmsg = (struct cmsghdr *)calloc(1,len);
    cmsg->cmsg_len = len;
    cmsg->cmsg_level = SOL_SOCKET;
    cmsg->cmsg_type = SCM_RIGHTS;

    *(int*)CMSG_DATA(cmsg) = fd;
    msg.msg_control = cmsg;
    msg.msg_controllen = len;

    int ret = sendmsg(sfd,&msg,0);
    ERROR_CHECK(ret,-1,"sendmsg");
     
    return 0;
}

int recvFd(int sfd,int *fd)
{
    struct msghdr msg;
    bzero(&msg,sizeof(msg));

    //用户接收
    struct iovec iov[1];
    char buf[20] = {0};
    iov[0].iov_base =buf;
    iov[0].iov_len = 20;
    msg.msg_iov = iov;
    msg.msg_iovlen = 1;

    //内核接收
    struct cmsghdr *cmsg;
    int len = CMSG_LEN(sizeof(int));
    cmsg = (struct cmsghdr*)calloc(1,len);
    cmsg->cmsg_len = len;
    cmsg->cmsg_level = SOL_SOCKET;
    cmsg->cmsg_type = SCM_RIGHTS;
    msg.msg_control = cmsg;
    msg.msg_controllen = len;
    int ret = recvmsg(sfd,&msg,0);
    ERROR_CHECK(ret,-1,"recvmsg");
    *fd = *(int*)CMSG_DATA(cmsg);
    return 0;
}

int main()
{
    int fds[2];
    socketpair(AF_LOCAL,SOCK_STREAM,0,fds);
    if(!fork())
    {
        sleep(1);
        close(fds[1]);
        int childfd;
        recvFd(fds[0],&childfd);
        char buf[128] = {0};
        printf("child: fd %d\n",childfd);
        read(childfd,buf,sizeof(buf));
        printf("child recvbuf:%s",buf);
    }
    else
    {
        close(fds[0]);
        int fd = open("file",O_RDWR);
        printf("main fd %d\n",fd);
        sendFd(fds[1],fd);
        wait(NULL);
    }
    return 0;
}
